package cc.eguid.tools;

import cc.eguid.tools.common.InstructionEnum;
import cc.eguid.tools.msg.*;
import cc.eguid.tools.ui.RemoteDesktop;
import cc.eguid.tools.ui.ClientPanel;
import com.alibaba.fastjson.JSONObject;

import javax.swing.*;
import java.io.*;
import java.net.Socket;

/**
 * 客户端实现
 */
public class LocalClient implements Runnable, RemoteEventListener {
    private String serverIp;
    private int serverPort;
    private Socket socket;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private RemoteDesktop remoteDesktop;
    private boolean connected;
    private ClientPanel clientPanel; // 添加对ClientPanel的引用

    String token;

    Double imageQuality = 1.0D;//图像质量

    public Double getImageQuality() {
        return imageQuality;
    }

    public void setImageQuality(Double imageQuality) {
        this.imageQuality = imageQuality;
    }

    public LocalClient(String serverIp, int serverPort, String token, RemoteDesktop remoteDesktop, ClientPanel clientPanel, Double imageQuality) {
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        this.remoteDesktop = remoteDesktop;
        this.clientPanel = clientPanel;
        this.token = token;
        this.imageQuality=imageQuality;
        this.connected = false;
        this.socket = null;
        this.in = null;
        this.out = null;
        remoteDesktop.addRemoteEventListener(this);
    }

    // 添加连接状态检查方法
    public boolean isConnected() {
        return connected && socket != null && !socket.isClosed();
    }


    @Override
    public void run() {
        System.out.println("开始连接: " + serverIp + ":" + serverPort);
        try {
            socket = new Socket(serverIp, serverPort);
            System.out.println("Socket连接成功");
        }catch(IOException e){
            System.out.println("连接到服务器失败: " + e.getMessage());
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(remoteDesktop, "连接失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                // 通知ClientPanel连接失败，重置UI状态
                if (clientPanel != null) {
                    clientPanel.onConnectionFailed();
                }
            });
            connected=false;
            // 清理资源（此时socket可能为null，disconnect方法会处理）
            disconnect();
            return;
        }
        if(socket==null){
            return;
        }
        try{
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());

            // 首先发送令牌进行验证
            out.writeObject(new TokenMessage(token));
            out.flush();

            // 等待服务端验证结果
            Object obj = in.readObject();

            if (obj instanceof AuthMessage) {
                AuthMessage authMsg = (AuthMessage) obj;
                if (authMsg.isSuccess()) {

                    //首次发送图像质量
                    JSONObject qualityJson = new JSONObject();
                    qualityJson.put("quality", imageQuality);
                    InstructionMessage instructionMessage = new InstructionMessage(InstructionEnum.IMAGE_QUALITY, qualityJson);
                    sendInstructionMessage(instructionMessage);

                    connected = true;
                    System.out.println("已连接到服务器");
                    // 通知ClientPanel连接成功
                    if (clientPanel != null) {
                        clientPanel.onConnectionSuccess();
                    }

                    // 接收屏幕图像
                    while (connected) {
                        if(in==null){
                            return;
                        }
                        try {
                            Object imageObj = in.readObject();
                            if (imageObj instanceof ImageMessage) {
                                ImageMessage imageMessage = (ImageMessage) imageObj;
                                SwingUtilities.invokeLater(() ->
                                        remoteDesktop.setDesktopImage(imageMessage.getImage())
                                );
                            } else {
                                throw new IOException("无效的服务端响应");
                            }
                        } catch (EOFException e) {
                            break;
                        } catch (Exception e) {
                            e.printStackTrace();
                            break;
                        }
                    }
                } else {
                    SwingUtilities.invokeLater(() -> {
                        JOptionPane.showMessageDialog(remoteDesktop,
                                "连接失败: " + authMsg.getMessage(),
                                "错误", JOptionPane.ERROR_MESSAGE);
                        // 通知ClientPanel连接失败，重置UI状态
                        if (clientPanel != null) {
                            clientPanel.onConnectionFailed();
                        }
                    });
                    // 清理资源
                    disconnect();
                    return;
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(remoteDesktop, "连接失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                // 通知ClientPanel连接失败，重置UI状态
                if (clientPanel != null) {
                    clientPanel.onConnectionFailed();
                }
            });
        } finally {
            disconnect();
        }
    }

    @Override
    public void onMouseEvent(String type, int x, int y, int button) {
        if (connected) {
            try {
                MouseEventMessage event = new MouseEventMessage(type, x, y, button);
                out.writeObject(event);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendInstructionMessage(InstructionMessage message){
        if (connected) {
            try {
                out.writeObject(message);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onKeyEvent(String type, int keyCode, char keyChar) {
        if (connected) {
            try {
                KeyEventMessage event = new KeyEventMessage(type, keyCode, keyChar);
                out.writeObject(event);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void disconnect() {
        connected = false;
        try {
            if (in != null) {
                in.close();
                in = null;
            }
            if (out != null) {
                out.close();
                out = null;
            }
            if (socket != null) {
                socket.close();
                socket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
